package net.ys.service;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.ys.bean.EvenOdd;
import net.ys.bean.KjResult;
import net.ys.dao.ApiDao;
import net.ys.utils.TimeUtil;
import net.ys.utils.Tools;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: NMY
 * @Date: 2021/6/22
 * @Time: 12:22
 */
@Service
public class ApiService {

    static int[] odd = new int[]{1, 3, 5, 7, 9, 11, 13, 15};
    static int[] even = new int[]{2, 4, 6, 8, 10, 12, 14, 16};

    static int hqNum = 6;

    static Cache<String, List<List<Integer>>> cache;
    static Cache<String, List<Integer>> cacheHqChoice;

    @Resource
    ApiDao apiDao;

    static {
        cache = CacheBuilder.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .concurrencyLevel(10)
                .recordStats()
                .build();

        cacheHqChoice = CacheBuilder.newBuilder()
                .maximumSize(6)
                .expireAfterWrite(30, TimeUnit.HOURS)
                .concurrencyLevel(10)
                .recordStats()
                .build();
    }

    /**
     * 随机生成彩票号码
     *
     * @param type    蓝球类型
     * @param account 生成注数
     * @param genId
     * @return
     */
    public List<List<Integer>> genNum(int type, int account, String genId) {

        List<List<Integer>> nums = new ArrayList<>();

        Random random = new Random();
        Set<Integer> lq = new HashSet<>();

        if (cacheHqChoice.size() == 0) {
            statisticsHq();
        }

        for (int i = 0; i < account; i++) {
            Set<Integer> list = new HashSet<>();
            int num = 1;
            while (list.size() < hqNum) {
                boolean add = list.add(cacheHqChoice.getIfPresent("red_" + num).get(random.nextInt(10)));
                if (add) {
                    num++;
                }
            }
            List<Integer> temp = new ArrayList<>(list);
            Collections.sort(temp);
            if (type == 0) {
                int l = even[random.nextInt(8)];
                while (true) {
                    if (!lq.contains(l)) {
                        lq.add(l);
                        temp.add(l);
                        break;
                    } else {
                        l = even[random.nextInt(8)];
                    }
                }
            } else if (type == 1) {
                int l = odd[random.nextInt(8)];
                while (true) {
                    if (!lq.contains(l)) {
                        lq.add(l);
                        temp.add(l);
                        break;
                    } else {
                        l = odd[random.nextInt(8)];
                    }
                }
            } else {
                int l = random.nextInt(16) + 1;
                while (true) {
                    if (!lq.contains(l)) {
                        lq.add(l);
                        temp.add(l);
                        break;
                    } else {
                        l = random.nextInt(16) + 1;
                    }
                }
            }
            nums.add(temp);
        }

        cache.put(genId, nums);

        return nums;
    }

    public boolean checkBuy() {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String now = format.format(new Date());
        return apiDao.queryBuy(now);
    }

    public boolean buy(String genId) throws Exception {

        List<List<Integer>> nums = cache.getIfPresent(genId);
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String now = format.format(new Date());

        boolean flag = apiDao.buy(nums, now);
        if (flag) {
            StringBuffer sb = new StringBuffer("购买日期：").append(now).append("\n彩票详情：\n");
            for (List<Integer> num : nums) {
                sb.append(num.toString().replaceAll("\\[|]", "")).append("\n");
            }
            Tools.dingTalkNotice(sb.toString());
        }
        return flag;
    }

    static Map<String, List<List<String>>> jc = new HashMap<>();

    /**
     * 兑奖
     */
    @Scheduled(cron = "0 10 7 * * MON,WED,FRI")
    public int cashPrize() throws Exception {
        //清空历史奖池
        jc.clear();

        //1、获取最新一期开奖结果
        String yesterday = TimeUtil.getYesterday();
        String tmp = apiDao.queryKjResult(yesterday);
        if (tmp == null) {
            KjResult cpKj = Tools.genCpResult();
            if (cpKj == null) {
                System.out.println("调用开奖接口查询失败");
                return 0;
            } else {
                apiDao.saveKjResult(cpKj);
            }
            tmp = apiDao.queryKjResult(cpKj.getLotteryDate());
        }

        List<String> kj = Arrays.asList(tmp.split(","));

        //2、获取最新购买的所有彩票
        String date = apiDao.queryNewBuyDate();
        List<Map<String, Object>> maps = apiDao.queryNewBuy(date);
        List<List<String>> list = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            list.add(Arrays.asList(map.get("cp_code").toString().split(",")));
        }

        //3、兑奖
        String lq = kj.get(6);
        List<String> hqs = kj.subList(0, 6);
        String lq_tmp;
        List<String> hqs_tmp;

        for (List<String> codes : list) {
            lq_tmp = codes.get(6);
            hqs_tmp = codes.subList(0, 6);

            int hq_num = getIntersection(hqs, hqs_tmp).size();

            if (lq.equals(lq_tmp)) {
                if (hq_num < 3) {
                    push("price_6", codes);
                } else if (hq_num == 3) {
                    push("price_5", codes);
                } else if (hq_num == 4) {
                    push("price_4", codes);
                } else if (hq_num == 5) {
                    push("price_3", codes);
                } else if (hq_num == 6) {
                    push("price_1", codes);
                }
            } else {
                if (hq_num == 4) {
                    push("price_5", codes);
                } else if (hq_num == 5) {
                    push("price_4", codes);
                } else if (hq_num == 6) {
                    push("price_2", codes);
                }
            }
        }

        //中奖通知
        if (jc.size() > 0) {
            StringBuffer sb = new StringBuffer("主人您有彩票中奖啦，详情如下：\n");
            for (Map.Entry<String, List<List<String>>> entry : jc.entrySet()) {
                sb.append(entry.getKey()).append("：\n");
                List<List<String>> value = entry.getValue();
                for (List<String> strings : value) {
                    sb.append("\t").append(strings.toString()).append("\n");
                }
            }
            Tools.dingTalkNotice(sb.toString());
        }
        System.out.println("中奖记录：" + jc);
        return jc.size();
    }

    static void push(String key, List<String> codes) {
        List<List<String>> price;
        if (jc.containsKey(key)) {
            price = jc.get(key);
        } else {
            price = new ArrayList<>();
        }
        price.add(codes);
        jc.put(key, price);
    }

    public void genCpResultHis() {
        for (int i = 1; i < 65; i++) {
            List<KjResult> results = Tools.genCpResultHis(i);
            if (results == null) {
                return;
            }
            for (KjResult result : results) {
                apiDao.saveKjResult(result);
            }
        }
    }

    public static <T> List<T> getIntersection(List<T> masterList, List<T> slaveList) {
        return masterList.stream().filter(slaveList::contains).collect(Collectors.toList());
    }

    /**
     * 统计红球
     */
    @Scheduled(cron = "0 10 1 * * *")
    public void statisticsHq() {
        //1、统计
        List<Map<String, Object>> options = apiDao.queryHqOptions();

        //2、清空
        apiDao.clearOptions();

        //3、插入
        apiDao.addHqOptions(options);

        //4、组装
        String choice;
        List<Integer> v;
        for (Map<String, Object> option : options) {
            v = new ArrayList<>();
            String key = String.valueOf(option.get("hq"));
            choice = String.valueOf(option.get("choice"));
            String[] split = choice.split(",");
            for (String s : split) {
                v.add(Integer.valueOf(s));
            }

            cacheHqChoice.put(key, v);
        }
    }

    public String forecast() {
        int blue = apiDao.currentBlue();
        List<Integer> list = apiDao.listBlueIds(blue);
        List<String> newList = new ArrayList<>();
        for (Integer integer : list) {
            newList.add(String.valueOf(integer + 1));
        }
        List<Map<String, Object>> blues = apiDao.forecast(newList);
        //奇数
        int odd = 0;
        //偶数
        int even = 0;
        Map<Integer, Integer> result = new HashMap<>();
        for (Map<String, Object> m : blues) {
            int item = Integer.parseInt(String.valueOf(m.get("blue")));
            if (item % 2 == 0) {
                even++;
            } else {
                odd++;
            }

            if (result.containsKey(item)) {
                result.put(item, result.get(item).intValue() + 1);
            } else {
                result.put(item, 1);
            }
        }

        StringBuffer sb = new StringBuffer();
        sb.append("当前篮球号码：").append(blue);
        if (odd > even) {
            sb.append("<span style=\"color: red;\">").append("奇数：").append(odd).append("</span>").append("偶数：").append(even).append(" 详情如下：<br/>");
        } else {
            sb.append("奇数：").append(odd).append("<span style=\"color: red;\">").append("偶数：").append(even).append("</span>").append(" 详情如下：<br/>");
        }
        List<EvenOdd> evenOdds = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : result.entrySet()) {
            evenOdds.add(new EvenOdd(entry.getKey(), entry.getValue()));
        }
        
        Collections.sort(evenOdds);

        for (EvenOdd evenOdd : evenOdds) {
            if (odd > even) {
                if (evenOdd.getNum() % 2 == 1) {
                    sb.append("<span style=\"color: red;\">").append(evenOdd.getNum()).append("-->").append(evenOdd.getAmount()).append("</span>").append("<br/>");
                } else {
                    sb.append(evenOdd.getNum()).append("-->").append(evenOdd.getAmount()).append("<br/>");
                }
            } else {
                if (evenOdd.getNum() % 2 == 0) {
                    sb.append("<span style=\"color: red;\">").append(evenOdd.getNum()).append("-->").append(evenOdd.getAmount()).append("</span>").append("<br/>");
                } else {
                    sb.append(evenOdd.getNum()).append("-->").append(evenOdd.getAmount()).append("<br/>");
                }
            }
//            sb.append(evenOdd.getNum()).append("-->").append(evenOdd.getAmount()).append("\t");
        }

        return sb.toString();
    }
}
